#!/usr/bin/env python

################################################################################
# Python Standard Library
################################################################################

import socket, struct, random, time

################################################################################
# Includes
################################################################################

import config
from libs.dae.ip import IP

################################################################################
# Realm Logon IP Proxifier
################################################################################

from protocols.bncs import BNCSPacket, RealmLogonResponse
from protocols.d2rp import D2RPSocket

class BNCS:
	def pack(packet):
		if packet.messageID == RealmLogonResponse:
			ip = socket.gethostbyname(packet.socket.source.host)
			port = random.randint(10000, 50000)
			
			# setup proxy
			sock = D2RPSocket()
			sock.source = IP(ip, port)
			sock.destination = IP(packet.ip, packet.port)
			sock.bind()
			sock.listen(5)
			
			config.write.append(sock)
			config.read.append(sock)
			
			packet.message = packet.message.replace(packet.message[20:24], socket.inet_aton(ip))
			packet.message = packet.message.replace(packet.message[24:28], struct.pack("<i", socket.htons(port)))
	
	pack = classmethod(pack)
	
	def unpack(packet):
		if packet.messageID == RealmLogonResponse:
			packet.mcpChunk1 = [None, None]
			
			packet.cookie, packet.status, packet.mcpChunk1[0], packet.mcpChunk1[1] = struct.unpack("<ii2i", packet.messageData[0:16])
			
			packet.ip = socket.inet_ntoa(packet.messageData[16:20])
			packet.port = socket.ntohs(struct.unpack("<i", packet.messageData[20:24])[0])
	
	unpack = classmethod(unpack)

################################################################################
# Game Server IP Proxifier
################################################################################

from protocols.d2rs import D2RSPacket, JoinGameResponse
from protocols.d2gp import D2GPSocket

class D2RS:
	def pack(packet):
		if packet.messageID == JoinGameResponse:
			ip = socket.gethostbyname(packet.socket.source.host)
			port = packet.port
			
			#setup proxy
			sock = D2GPSocket()
			sock.source = IP(ip, port)
			sock.destination = IP(packet.ip, packet.port)
			sock.bind()
			sock.listen(5)
			
			config.write.append(sock)
			config.read.append(sock)
			
			packet.message = packet.message.replace(packet.message[9:13], socket.inet_aton(ip))
	
	pack = classmethod(pack)
	
	def unpack(packet):
		print "D2RS"
		if packet.messageID == JoinGameResponse:
			packet.requestID, packet.gameToken, packet.unknown1 = struct.unpack("<HHH", packet.messageData[0:6])
			
			packet.ip = socket.inet_ntoa(packet.messageData[6:10])
			packet.port = 4000
			
			packet.gameHash, packet.result = struct.unpack("<HH", packet.messageData[10:14])
	
	unpack = classmethod(unpack)

################################################################################
# Proxy
################################################################################

from protocols.bnp import BNPSocket

class Proxy:
	def initialize(self, greenvex):
		if config.isCommand("ip"):
			ip = config.isCommand("ip")
		else:
			ip = ''
		
		sock = BNPSocket()
		sock.source = IP(ip, 6112)
		sock.destination = IP(config.realm, 6112)
		sock.bind()
		sock.listen(5)
		
		config.write.append(sock)
		config.read.append(sock)
		
		BNCSPacket.addEventListener("pack", BNCS.pack)
		BNCSPacket.addEventListener("unpack", BNCS.unpack)
		
		D2RSPacket.addEventListener("pack", D2RS.pack)
		D2RSPacket.addEventListener("unpack", D2RS.unpack)

################################################################################
# Main
################################################################################

def main():
	return Proxy()